#define		_CRT_SECURE_NO_WARNINGS
#include        <stdio.h>
#include        <stdlib.h>
#include        <string.h>
#include	"tank.h"

#ifdef		__linux__
#include        <sys/types.h>
#include        <sys/socket.h>
#include        <netinet/in.h>
#include        <arpa/inet.h>
#endif				/* __linux__ */

#ifdef		_WIN32
#include	<windows.h>
#include	<winsock.h>
#pragma		comment(lib, "ws2_32.lib")
#endif				/* _WIN32 */

#define         PORT            6000
#define		MAX_TANK_NUM	10
#define         MINIMAP_WIDTH   0.500
#define         MINIMAP_HEIGHT  0.309

struct  Item {
enum    Skill   name;
float           x;
float           speed;
};

int			tank0_id;
int			tanks_count;
int			items_count;
int                     client_socket;
struct	Tank		tanks[MAX_TANK_NUM];
struct  Item		items[MAX_ITEM_NUM];

void
net_init()
{
		struct  sockaddr_in     client_addr, server_addr;
        int               server_addr_length;
		char server_ip[] = "000.000.000.000";
		FILE *fp;
		fp = fopen("server.txt", "r");
	    if (fp != NULL) {
			fscanf(fp, "%s", server_ip);
		}
#ifdef  _WIN32
		WSADATA	WSAData;
		WSAStartup(MAKEWORD(1, 1), &WSAData);
#endif			/* _WIN32 */
        memset(&client_addr, 0, sizeof(client_addr));
        client_addr.sin_family = AF_INET;
        client_addr.sin_addr.s_addr = htons(INADDR_ANY);
        client_addr.sin_port = htons(0);
        client_socket = socket(AF_INET, SOCK_STREAM, 0);
        if(client_socket < 0) {
                net_flag = 0;
		return;
	}
     	if(bind(client_socket, (struct sockaddr *)&client_addr, sizeof(client_addr))) {
                net_flag = 0;
		return;
	}
	memset(&server_addr, 0, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        if((server_addr.sin_addr.s_addr = inet_addr(server_ip)) == 0) {
                net_flag = 0;
                return;
        }
        server_addr.sin_port = htons(PORT);
        server_addr_length = sizeof(server_addr);
        if(connect(client_socket, (struct sockaddr *)&server_addr, server_addr_length) < 0) {
                net_flag = 0;
                return;
        }
	net_flag = 1;
	return;
}

void
net_send(void *buffer, int n)
{
	send(client_socket, buffer, n, 0);
	return;
}

void
net_get(void *buffer, int n)
{
	if(recv(client_socket, buffer, n, 0) == 0) {
		exit(1);
	}
	return;
}	
	
void
send_req(enum Net req)
{
	net_send(&req, sizeof(req));
	return;
}

int
find_tank(int id)
{
	int i;
	for(i = 0; i < tanks_count; i++) {
		if(tanks[i].id == id)
			return i;
	}
	return -1;
}

int
load_self()
{
	int i = find_tank(tank0_id);
	if(i != -1) {
		tank0 = tanks[i];
	} else {
		return -1;
	}
	return 0;
}

void
show_tanks()
{
	int i;
	if(wait_flag) {
		wait_flag |= 1;
		show_wait();
		if(take_part()) 
			wait_flag &= 0;
	}
	for(i = 0; i < tanks_count; i++) {
		show_tank(&tanks[i]);
	}
	return;
}

void
show_items()
{
	int i;
	for(i = 0; i < items_count; i++) {
		show_item(items[i].x, items[i].name);
	}
	return;
}	

int
take_part()
{
	send_req(NEW_TANK);
	net_get(&tank0_id, sizeof(tank0_id));
	return tank0_id;
}		

void
get_tanks()
{
	send_req(GET_TANKS);
	net_get(&tanks_count, sizeof(tanks_count));
	net_get(tanks, sizeof(struct Tank) * MAX_TANK_NUM);
	if(load_self() == -1)
		wait_flag = 1;
	return;
}

void
get_items()
{
	send_req(GET_ITEMS);
	net_get(&items_count, sizeof(items_count));
	if (items_count == 0)
		return;
	net_get(&items, sizeof(items[0]) * MAX_ITEM_NUM);
	return;
}
	
void
add_speed(float speed)
{
	if(!net_flag) {
		tank0.base_speed += speed;
		return;
	}
	send_req(ADD_SPEED);
	net_send(&speed, sizeof(speed));
	return;
}

void
get_map()
{
	send_req(GET_MAP);
	net_get(&vertex_count, sizeof(vertex_count));
	net_get(mapvertex, MAX_VERTEX);
	return;
}

void
show_minitank(float x, float y)
{
        float _x = (x / (mapvertex[vertex_count-4] - mapvertex[2])) * (MINIMAP_WIDTH * 0.9);
        float _y = (y / 25.0) * MINIMAP_HEIGHT + MINIMAP_HEIGHT / 2;
        glBegin(GL_POINTS);
                glVertex2f(_x, _y);
        glEnd();
        return;
}

void
show_miniroad()
{
	int i;
	float x, y;
	glLineWidth(4.0);
	glColor3f(0.5, 0.5, 0.5);
	glBegin(GL_LINE_STRIP);
	for(i = 2; i < vertex_count - 2; i += 2) {
		x = (mapvertex[i] / (mapvertex[vertex_count-4] - mapvertex[2])) * (MINIMAP_WIDTH * 0.9);
        	y = (mapvertex[i+1] / 25.0) * MINIMAP_HEIGHT + MINIMAP_HEIGHT / 2;
		glVertex2f(x, y);
	}
	glEnd();
	return;
}

void
show_minimap()
{
        int i;
        float map_x = eye_x - 0.9;
        float map_y = eye_y + 0.5;
        glColor4f(0.4, 0.4, 0.4, 0.6);
        glPushMatrix();
        glTranslatef(map_x, map_y, 0.0);
        glBegin(GL_QUADS);
                glVertex2f(0.0, 0.0);
                glVertex2f(MINIMAP_WIDTH, 0.0);
                glVertex2f(MINIMAP_WIDTH, MINIMAP_HEIGHT);
                glVertex2f(0.0, MINIMAP_HEIGHT);
        glEnd();
	glTranslatef(0.05 * MINIMAP_WIDTH, 0.0, 0.0);
	show_miniroad();
	glPointSize(4.0);
	glColor3f(0.0, 0.0, 1.0);
	show_minitank(mapvertex[2], mapvertex[3]);
	show_minitank(mapvertex[vertex_count-4], mapvertex[vertex_count-3]);
	glColor3f(0.0, 1.0, 0.0);
        for(i = 0; i < tanks_count; i++) {
                show_minitank(tanks[i].posx, tanks[i].posy);
        }
	glColor3f(1.0, 0.0, 0.0);
        show_minitank(tank0.posx, tank0.posy);
        glPopMatrix();
        return;
}

void
use_skill(int box_num)
{
        if(!start_flag | !net_flag) return;
        if(all_time - skills[box_num].use_time < skills[box_num].cool_time) return;
        skills[box_num].use_time = all_time;
        send_req(SKILL);
	net_send(&skills[box_num].skill_name, sizeof(skills[box_num].skill_name));
	switch(skills[box_num].skill_name) {
		case MISSILE: play_missile(); break;
		default: break;
	}
        return;
}
	
